#include "ModbusProtocol.h"

ModbusProtocol::ModbusProtocol(QObject *parent) :
    BaseProtocol(parent)
{
    this->m_protocolType = ProtocolType::ModbusProtocol;
    ModbusListXml *modbusListXml = ModbusListXml::getInstance();
    m_deviceAddressList = modbusListXml->deviceAddressList();
    m_readFunctionCodeList.append(ModbusProtocol::ReadCoilRegister);
    m_readFunctionCodeList.append(ModbusProtocol::ReadDiscreteCoilRegister);
    m_readFunctionCodeList.append(ModbusProtocol::ReadHoldRegister);
    m_readFunctionCodeList.append(ModbusProtocol::ReadInputRegister);
    m_writeFunctionCodeList.append(ModbusProtocol::WriteSignalCoilRegister);
    m_writeFunctionCodeList.append(ModbusProtocol::WriteSignalHoldRegister);
    m_writeFunctionCodeList.append(ModbusProtocol::WriteMultCoilRegister);
    m_writeFunctionCodeList.append(ModbusProtocol::WriteMultHoldRegister);
}
QList<Package> ModbusProtocol::parseData(QByteArray data)
{
    quint8  checkSteps = CHECK_HEAD;     //当前解析状态
    quint16 lengthCount;                 //数据长度计算
    quint16 bodyLength;
    QByteArray dataArray;
    quint16 crc16=0;
    QList<Package> packageList;
    qDebug()<<"ModbusData Protocol now;";
    for(int i=0; i<data.size(); i++)
    {
        quint8 byte = data.at(i);
        switch(checkSteps)
        {
            case CHECK_HEAD:   //检查数据头
                 foreach(const quint8 &deviceAddress,m_deviceAddressList)
                 {
                     if(byte == deviceAddress)
                     {
                 //        qDebug()<<"ModbusData Protocol now=1;";
                         lengthCount = 0;
                         bodyLength = 0;
                         dataArray.clear();
                         dataArray.append(byte);
                         checkSteps = CHECK_FUNCTION;
                     }
                 }
            break;

            case CHECK_FUNCTION:   //接收数据功能
          //      qDebug()<<"ModbusData Protocol now=2;";
                 if(m_readFunctionCodeList.contains(byte))
                 {
                    // bodyLength = 4;
                     dataArray.append(byte);
                     checkSteps = CHECK_LENGTH;
                 }
                 else if(m_writeFunctionCodeList.contains(byte))
                 {
              //      qDebug()<<"ModbusData Protocol now=4;";
                     bodyLength = 4;
                     dataArray.append(byte);
                     checkSteps = CHECK_BODY;
                 }
                 else
                 {
                     checkSteps = CHECK_HEAD;
                 }
            break;

            case CHECK_LENGTH:

                 dataArray.append(byte);
                 bodyLength = byte;
         //        qDebug()<<"ModbusData Protocol now=3;bodylength="<<bodyLength;
                 checkSteps = CHECK_BODY;
                 break;

            case CHECK_BODY:    //接收数据
          //         qDebug()<<"ModbusData Protocol now=4;";
                 lengthCount++;
                 dataArray.append(byte);
          //      qDebug()<<"ModbusData Protocol now=4;now lengthCOunt="<<lengthCount;
                 if(lengthCount == bodyLength)
                 {
                     lengthCount = 0;
                     checkSteps = CHECK_CHECKCODE;
                 }
                 break;

            case CHECK_CHECKCODE:
               // qDebug()<<"ModbusData Protocol now=5;";
                 lengthCount++;
                 dataArray.append(byte);
                 if(lengthCount == 1)
                 {
                     crc16 = quint16(byte)<<8;
                 }
                 if(lengthCount == 2)
                 {
                     lengthCount = 0;
                     crc16 |= byte;
                     if(CheckCode::computeCRC16(dataArray,dataArray.size()-2) == crc16)
                     {
                         Package package;
                         package.setHead(dataArray.mid(0,1));
                         package.setFunction(dataArray.mid(1,1).toHex().toInt(0,16));
                         package.setBody(dataArray.mid(2,bodyLength+1));
                         package.setCheckCode(dataArray.mid(3+bodyLength,2).toHex().toInt(0,16));
                         package.setId(dataArray.mid(0,2).toHex().toInt(0,16));
                         packageList.append(package);
             //            qDebug()<<"modbusboot";
                     }
                     checkSteps = CHECK_HEAD;
                 }
        }
    }

    return packageList;
}

QByteArray ModbusProtocol::generateData(Package package)
{
    QByteArray data;

    data.append(package.head());
    data.append(DataTypeConver::intToByteArray(package.function(),1));
    data.append(package.body());
    quint16 crc16 = CheckCode::computeCRC16(data,data.size());
    data.append(DataTypeConver::intToByteArray(crc16,2));

    return data;
}
QByteArray ModbusProtocol::getmodbusData(quint8 deviceAddr,quint8 FunctionCode,quint16 registerStartAddress)
{
    quint16 crc16;
    QByteArray SetModbusData;

    SetModbusData.resize(8);
    SetModbusData[0]=deviceAddr;
    SetModbusData[1]=FunctionCode;
    SetModbusData[2]=(registerStartAddress & 0xff00)>>8;
    SetModbusData[3]=registerStartAddress & 0xff;
    SetModbusData[4]=0x00;
    SetModbusData[5]=0x01;
    crc16=CheckCode::computeCRC16(SetModbusData,6);
    SetModbusData[6]=(crc16& 0xff00)>>8;
    SetModbusData[7]=crc16 & 0xff;

    return SetModbusData;
}
